home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / source / chapter10 / isohex10_4 / isohex10_4.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-01  |  22.5 KB  |  1,096 lines

  1. /*****************************************************************************
  2. IsoHex10_4.cpp
  3. Ernest S. Pazera
  4. 27JUN2000
  5. Start a WIN32 Application Workspace, add in this file
  6. Needs ddraw.lib,  and dxguid.lib
  7. Needs GDICanvas.h/cpp
  8. Needs DDFuncs.h/cpp
  9. Needs tileset.h/cpp
  10. *****************************************************************************/
  11.  
  12. //////////////////////////////////////////////////////////////////////////////
  13. //INCLUDES
  14. //////////////////////////////////////////////////////////////////////////////
  15. #define WIN32_LEAN_AND_MEAN  
  16.  
  17. #include <windows.h>   
  18. #include "GDICanvas.h"
  19. #include "ddraw.h"
  20. #include "DDFuncs.h"
  21. #include "mmsystem.h"
  22. #include "TileSet.h"
  23.  
  24. //////////////////////////////////////////////////////////////////////////////
  25. //DEFINES
  26. //////////////////////////////////////////////////////////////////////////////
  27. //name for our window class
  28. #define WINDOWCLASS "ISOHEX10"
  29. //title of the application
  30. #define WINDOWTITLE "IsoHex 10-4: Reversi"
  31.  
  32. const int PLAYERONE=0;//black player
  33. const int PLAYERTWO=1;//white player
  34. const int PIECEEMPTY=-1;//empty square
  35. const int PIECEBLACK=0;//black piece
  36. const int PIECEWHITE=1;//white piece
  37. const int PIECETRANSIT=2;//animated flip
  38.  
  39. //game states
  40. const int GS_NONE=-1;
  41. const int GS_WAITFORINPUT=0;
  42. const int GS_NEWGAME=1;
  43. const int GS_NEXTPLAYER=2;
  44. const int GS_FLIP=3;
  45.  
  46. //directions
  47. const int DIR_NORTH=0;
  48. const int DIR_NORTHEAST=1;
  49. const int DIR_EAST=2;
  50. const int DIR_SOUTHEAST=3;
  51. const int DIR_SOUTH=4;
  52. const int DIR_SOUTHWEST=5;
  53. const int DIR_WEST=6;
  54. const int DIR_NORTHWEST=7;
  55. const int DIR_COUNT=8;
  56.  
  57. //ai levels
  58. const int AI_HUMAN=0;
  59. const int AI_RANDOM=1;
  60. const int AI_GREEDY=2;
  61. const int AI_MISER=3;
  62. const int AI_COUNT=4;
  63.  
  64. //////////////////////////////////////////////////////////////////////////////
  65. //PROTOTYPES
  66. //////////////////////////////////////////////////////////////////////////////
  67. bool Prog_Init();//game data initalizer
  68. void Prog_Loop();//main game loop
  69. void Prog_Done();//game clean up
  70. //save/restore board to backup board
  71. void SaveBoard();
  72. void RestoreBoard();
  73. //game manipulation
  74. void SetUpBoard();
  75. void ShowBoard();
  76. //move
  77. void ScanForMoves(int plyr);
  78. bool AnyValidMoves(int plyr);
  79. bool ValidMove(int plyr,int x,int y);
  80. bool ValidRun(int plyr,int x,int y,int dir);
  81. //move x and y in direction
  82. int DeltaX(int dir);
  83. int DeltaY(int dir);
  84. //make a move
  85. void MakeMove(int plyr,int x, int y);
  86. void FinishMove(int plyr);
  87. //ai move functions
  88. void MakeRandomMove(int plyr);
  89. void MakeGreedyMove(int plyr);
  90. void MakeMiserMove(int plyr);
  91. //score evaulation
  92. int GetScore(int plyr);
  93. void ShowScores();
  94. //last move
  95. void SetLastMove(int x, int y);
  96. //show players
  97. void ShowPlayers();
  98.  
  99. //////////////////////////////////////////////////////////////////////////////
  100. //GLOBALS
  101. //////////////////////////////////////////////////////////////////////////////
  102. HINSTANCE hInstMain=NULL;//main application handle
  103. HWND hWndMain=NULL;//handle to our main window
  104. //IDirectDraw7 Pointer
  105. LPDIRECTDRAW7 lpdd=NULL;
  106. //surfaces
  107. LPDIRECTDRAWSURFACE7 lpddsMain=NULL;
  108. LPDIRECTDRAWSURFACE7 lpddsBack=NULL;
  109. //tileset
  110. CTileSet tsReversi;
  111.  
  112. //tile information structure
  113. struct REVERSITILE
  114. {
  115.     int iTileNum;//base tile number for square
  116.     bool bHilite;//hilited, or not hilited
  117.     int iPiece;//piece occupying square
  118.     bool bLastMove;//last move made
  119. };
  120.  
  121. //the board
  122. REVERSITILE Board[8][8];
  123. //backup board
  124. REVERSITILE BackUpBoard[8][8];
  125. //current player
  126. int iPlayer=0;
  127. //counter for animated "flipping" of pieces
  128. int iAnimation=0;
  129. //ai level for the players
  130. int iAILevel[2];
  131.  
  132. //gamestate
  133. int iGameState=GS_NONE;
  134.  
  135. //////////////////////////////////////////////////////////////////////////////
  136. //WINDOWPROC
  137. //////////////////////////////////////////////////////////////////////////////
  138. LRESULT CALLBACK TheWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  139. {
  140.     //which message did we get?
  141.     switch(uMsg)
  142.     {
  143.     case WM_LBUTTONUP:
  144.         {
  145.             //grab mouse position
  146.             POINT ptMouse;
  147.             ptMouse.x=LOWORD(lParam);
  148.             ptMouse.y=HIWORD(lParam);
  149.  
  150.             //test rectangle
  151.             RECT rcTest;
  152.             //get tile width and height
  153.             int iTileWidth=tsReversi.GetTileList()[0].rcSrc.right-tsReversi.GetTileList()[0].rcSrc.left;
  154.             int iTileHeight=tsReversi.GetTileList()[0].rcSrc.bottom-tsReversi.GetTileList()[0].rcSrc.top;
  155.  
  156.             //calc board rect
  157.             SetRect(&rcTest,(400-iTileWidth*4),(300-iTileHeight*4),(400+iTileWidth*4),(300+iTileHeight*4));
  158.             //point on board?
  159.             if(PtInRect(&rcTest,ptMouse))
  160.             {
  161.                 //if we are waiting for input and the ai is "human", check for inside the board
  162.                 if((iGameState==GS_WAITFORINPUT) && (iAILevel[iPlayer]==AI_HUMAN))
  163.                 {
  164.                     //find board position
  165.                     int BoardX=(ptMouse.x-rcTest.left)/iTileWidth;
  166.                     int BoardY=(ptMouse.y-rcTest.top)/iTileHeight;
  167.  
  168.                     //check for a valid square
  169.                     if(ValidMove(iPlayer,BoardX,BoardY))
  170.                     {
  171.                     //make the move
  172.                         MakeMove(iPlayer,BoardX,BoardY);
  173.                         SetLastMove(BoardX,BoardY);
  174.                         iGameState=GS_FLIP;
  175.                     }
  176.                 }
  177.                 //if a game is over, start a new game by clicking on the board
  178.                 if(iGameState==GS_NONE)
  179.                 {
  180.                     iGameState=GS_NEWGAME;
  181.                 }
  182.             }
  183.             //check for the AI indicators
  184.             //player one
  185.             SetRect(&rcTest,0,600-iTileHeight,iTileWidth,600);
  186.             //check for mouse in rect
  187.             if(PtInRect(&rcTest,ptMouse))
  188.             {
  189.                 iAILevel[PLAYERONE]++;
  190.                 iAILevel[PLAYERONE]%=AI_COUNT;
  191.             }
  192.             //player two
  193.             SetRect(&rcTest,iTileWidth,600-iTileHeight,iTileWidth*2,600);
  194.             //check for mouse in rect
  195.             if(PtInRect(&rcTest,ptMouse))
  196.             {
  197.                 iAILevel[PLAYERTWO]++;
  198.                 iAILevel[PLAYERTWO]%=AI_COUNT;
  199.             }
  200.         }break;
  201.     case WM_KEYDOWN:
  202.         {
  203.             //check for escape key
  204.             if(wParam==VK_ESCAPE)
  205.             {
  206.                 DestroyWindow(hWndMain);
  207.             }
  208.  
  209.             //check for F2(new game)
  210.             if(wParam==VK_F2)
  211.             {
  212.                 iGameState=GS_NEWGAME;
  213.             }
  214.  
  215.             return(0);//handled message
  216.         }break;
  217.     case WM_DESTROY://the window is being destroyed
  218.         {
  219.  
  220.             //tell the application we are quitting
  221.             PostQuitMessage(0);
  222.  
  223.             //handled message, so return 0
  224.             return(0);
  225.  
  226.         }break;
  227.     case WM_PAINT://the window needs repainting
  228.         {
  229.             //a variable needed for painting information
  230.             PAINTSTRUCT ps;
  231.             
  232.             //start painting
  233.             HDC hdc=BeginPaint(hwnd,&ps);
  234.  
  235.             /////////////////////////////
  236.             //painting code would go here
  237.             /////////////////////////////
  238.  
  239.             //end painting
  240.             EndPaint(hwnd,&ps);
  241.                         
  242.             //handled message, so return 0
  243.             return(0);
  244.         }break;
  245.     }
  246.  
  247.     //pass along any other message to default message handler
  248.     return(DefWindowProc(hwnd,uMsg,wParam,lParam));
  249. }
  250.  
  251.  
  252. //////////////////////////////////////////////////////////////////////////////
  253. //WINMAIN
  254. //////////////////////////////////////////////////////////////////////////////
  255. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
  256. {
  257.     //assign instance to global variable
  258.     hInstMain=hInstance;
  259.  
  260.     //create window class
  261.     WNDCLASSEX wcx;
  262.  
  263.     //set the size of the structure
  264.     wcx.cbSize=sizeof(WNDCLASSEX);
  265.  
  266.     //class style
  267.     wcx.style=CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  268.  
  269.     //window procedure
  270.     wcx.lpfnWndProc=TheWindowProc;
  271.  
  272.     //class extra
  273.     wcx.cbClsExtra=0;
  274.  
  275.     //window extra
  276.     wcx.cbWndExtra=0;
  277.  
  278.     //application handle
  279.     wcx.hInstance=hInstMain;
  280.  
  281.     //icon
  282.     wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION);
  283.  
  284.     //cursor
  285.     wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
  286.  
  287.     //background color
  288.     wcx.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
  289.  
  290.     //menu
  291.     wcx.lpszMenuName=NULL;
  292.  
  293.     //class name
  294.     wcx.lpszClassName=WINDOWCLASS;
  295.  
  296.     //small icon
  297.     wcx.hIconSm=NULL;
  298.  
  299.     //register the window class, return 0 if not successful
  300.     if(!RegisterClassEx(&wcx)) return(0);
  301.  
  302.     //create main window
  303.     hWndMain=CreateWindowEx(0,WINDOWCLASS,WINDOWTITLE, WS_POPUP | WS_VISIBLE,0,0,320,240,NULL,NULL,hInstMain,NULL);
  304.  
  305.     //error check
  306.     if(!hWndMain) return(0);
  307.  
  308.     //if program initialization failed, then return with 0
  309.     if(!Prog_Init()) return(0);
  310.  
  311.     //message structure
  312.     MSG msg;
  313.  
  314.     //message pump
  315.     for(;;)    
  316.     {
  317.         //look for a message
  318.         if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  319.         {
  320.             //there is a message
  321.  
  322.             //check that we arent quitting
  323.             if(msg.message==WM_QUIT) break;
  324.             
  325.             //translate message
  326.             TranslateMessage(&msg);
  327.  
  328.             //dispatch message
  329.             DispatchMessage(&msg);
  330.         }
  331.  
  332.         //run main game loop
  333.         Prog_Loop();
  334.     }
  335.     
  336.     //clean up program data
  337.     Prog_Done();
  338.  
  339.     //return the wparam from the WM_QUIT message
  340.     return(msg.wParam);
  341. }
  342.  
  343. //////////////////////////////////////////////////////////////////////////////
  344. //INITIALIZATION
  345. //////////////////////////////////////////////////////////////////////////////
  346. bool Prog_Init()
  347. {
  348.     //seed random number generator
  349.     srand((int)GetTickCount());
  350.  
  351.     //create directdraw interface
  352.     lpdd=LPDD_Create(hWndMain,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);
  353.  
  354.     //set display mode(800x600x16)
  355.     lpdd->SetDisplayMode(800,600,16,0,0);
  356.  
  357.     //create primary surface
  358.     lpddsMain=LPDDS_CreatePrimary(lpdd,1);
  359.  
  360.     //get back buffer
  361.     lpddsBack=LPDDS_GetSecondary(lpddsMain);
  362.  
  363.     //load in the tileset
  364.     tsReversi.Load(lpdd,"IsoHex10_4.bmp");
  365.  
  366.     //clear the board
  367.     SetUpBoard();
  368.     //set game state
  369.     iGameState=GS_NONE;
  370.  
  371.     //set initial AI levels
  372.     iAILevel[0]=AI_HUMAN;
  373.     iAILevel[1]=AI_RANDOM;
  374.  
  375.     return(true);//return success
  376. }
  377.  
  378. //////////////////////////////////////////////////////////////////////////////
  379. //CLEANUP
  380. //////////////////////////////////////////////////////////////////////////////
  381. void Prog_Done()
  382. {    
  383.     //release primary
  384.     LPDDS_Release(&lpddsMain);
  385.  
  386.     //release ddraw
  387.     LPDD_Release(&lpdd);
  388. }
  389.  
  390. //////////////////////////////////////////////////////////////////////////////
  391. //MAIN GAME LOOP
  392. //////////////////////////////////////////////////////////////////////////////
  393. void Prog_Loop()
  394. {
  395.     //clear out back buffer
  396.     DDBLTFX ddbltfx;
  397.     DDBLTFX_ColorFill(&ddbltfx,0);
  398.     lpddsBack->Blt(NULL,NULL,NULL,DDBLT_WAIT | DDBLT_COLORFILL,&ddbltfx);
  399.  
  400.     switch(iGameState)
  401.     {
  402.         case GS_WAITFORINPUT:
  403.             {
  404.                 //make move appropriate to the AI
  405.                 switch(iAILevel[iPlayer])
  406.                 {
  407.                 case AI_RANDOM:
  408.                     {
  409.                         MakeRandomMove(iPlayer);
  410.                     }break;
  411.                 case AI_GREEDY:
  412.                     {
  413.                         MakeGreedyMove(iPlayer);
  414.                     }break;
  415.                 case AI_MISER:
  416.                     {
  417.                         MakeMiserMove(iPlayer);
  418.                     }break;
  419.                 }
  420.             }break;
  421.         case GS_NEWGAME:
  422.             {
  423.                 //clear the board
  424.                 SetUpBoard();
  425.  
  426.                 //set player
  427.                 iPlayer=PLAYERTWO;
  428.  
  429.                 //change gamestate
  430.                 iGameState=GS_NEXTPLAYER;
  431.             }break;
  432.         case GS_NEXTPLAYER:
  433.             {
  434.                 //scan for moves
  435.                 ScanForMoves(iPlayer);
  436.  
  437.                 //if no more valid moves, game over
  438.                 if((!AnyValidMoves(PLAYERTWO))  && (!AnyValidMoves(PLAYERONE)))
  439.                 {
  440.                     iGameState=GS_NONE;
  441.                 }
  442.                 else
  443.                 {
  444.                     //find if opponent has any moves
  445.                     if(AnyValidMoves(1-iPlayer))
  446.                     {
  447.                         iPlayer=1-iPlayer;
  448.                     }
  449.  
  450.                     //scan for moves by current player
  451.                     ScanForMoves(iPlayer);
  452.  
  453.                     //get next move
  454.                     iGameState=GS_WAITFORINPUT;
  455.                 }
  456.             }break;
  457.         case GS_FLIP:
  458.             {
  459.                 switch(iPlayer)
  460.                 {
  461.                 case PLAYERTWO:
  462.                     {
  463.                         if(iAnimation==0)
  464.                         {
  465.                             FinishMove(iPlayer);
  466.                             iGameState=GS_NEXTPLAYER;
  467.                         }
  468.                         else
  469.                         {
  470.                             iAnimation--;
  471.                         }
  472.                     }break;
  473.                 case PLAYERONE:
  474.                     {
  475.                         if(iAnimation==14)
  476.                         {
  477.                             FinishMove(iPlayer);
  478.                             iGameState=GS_NEXTPLAYER;
  479.                         }
  480.                         else
  481.                         {
  482.                             iAnimation++;
  483.                         }
  484.                     }break;
  485.                 }
  486.             }break;
  487.     }
  488.     
  489.     //show the board
  490.     ShowBoard();
  491.  
  492.     //show the scores
  493.     ShowScores();
  494.  
  495.     //show players
  496.     ShowPlayers();
  497.  
  498.     //flip
  499.     lpddsMain->Flip(NULL,DDFLIP_WAIT);
  500. }
  501.  
  502. void SaveBoard()
  503. {
  504.     //loop through board squares
  505.     for(int x=0;x<8;x++)
  506.     {
  507.         for(int y=0;y<8;y++)
  508.         {
  509.             //save square to backup
  510.             BackUpBoard[x][y]=Board[x][y];
  511.         }
  512.     }
  513. }
  514.  
  515. void RestoreBoard()
  516. {
  517.     //loop through board squares
  518.     for(int x=0;x<8;x++)
  519.     {
  520.         for(int y=0;y<8;y++)
  521.         {
  522.             //restore from backup
  523.             Board[x][y]=BackUpBoard[x][y];
  524.         }
  525.     }
  526. }
  527.  
  528. void SetUpBoard()
  529. {
  530.     //loop through board squares
  531.     for(int x=0;x<8;x++)
  532.     {
  533.         for(int y=0;y<8;y++)
  534.         {
  535.             //setup board square
  536.             Board[x][y].bHilite=false;
  537.             Board[x][y].iTileNum=0;
  538.             Board[x][y].iPiece=PIECEEMPTY;
  539.             Board[x][y].bLastMove=false;
  540.         }
  541.     }
  542.  
  543.     //place initial pieces
  544.     Board[3][3].iPiece=PIECEWHITE;
  545.     Board[4][4].iPiece=PIECEWHITE;
  546.     Board[3][4].iPiece=PIECEBLACK;
  547.     Board[4][3].iPiece=PIECEBLACK;
  548.  
  549.     //place corner markers
  550.     //upper left
  551.     Board[1][1].iTileNum=1;
  552.     Board[2][1].iTileNum=2;
  553.     Board[1][2].iTileNum=3;
  554.     Board[2][2].iTileNum=4;
  555.     //upper right
  556.     Board[5][1].iTileNum=1;
  557.     Board[6][1].iTileNum=2;
  558.     Board[5][2].iTileNum=3;
  559.     Board[6][2].iTileNum=4;
  560.     //lower left
  561.     Board[1][5].iTileNum=1;
  562.     Board[2][5].iTileNum=2;
  563.     Board[1][6].iTileNum=3;
  564.     Board[2][6].iTileNum=4;
  565.     //lower right
  566.     Board[5][5].iTileNum=1;
  567.     Board[6][5].iTileNum=2;
  568.     Board[5][6].iTileNum=3;
  569.     Board[6][6].iTileNum=4;
  570.  
  571.     //save board
  572.     SaveBoard();
  573. }
  574.  
  575. void ShowBoard()
  576. {
  577.     int iTile=0;
  578.     int TileX=0;
  579.     int TileY=0;
  580.     //retrieve tile width and height(assuming all tiles are as wide/high as tile 0)
  581.     int iTileWidth=tsReversi.GetTileList()[0].rcSrc.right-tsReversi.GetTileList()[0].rcSrc.left;
  582.     int iTileHeight=tsReversi.GetTileList()[0].rcSrc.bottom-tsReversi.GetTileList()[0].rcSrc.top;
  583.     //loop through board squares
  584.     for(int y=0;y<8;y++)
  585.     {
  586.         //tile y position
  587.         TileY=y*iTileHeight+(600-iTileHeight*8)/2;
  588.         for(int x=0;x<8;x++)
  589.         {
  590.             //tile x position
  591.             TileX=x*iTileWidth+(800-iTileWidth*8)/2;
  592.  
  593.             //show background
  594.             //base tile
  595.             iTile=Board[x][y].iTileNum;
  596.             //modify for hilite
  597.             if(Board[x][y].bHilite)
  598.             {
  599.                 iTile+=5;
  600.             }
  601.             tsReversi.PutTile(lpddsBack,TileX,TileY,iTile);
  602.  
  603.             //show piece
  604.             iTile=Board[x][y].iPiece;
  605.             switch(iTile)
  606.             {
  607.             case PIECEEMPTY:
  608.                 {
  609.                     //do nothing
  610.                 }break;
  611.             case PIECEWHITE:
  612.                 {
  613.                     //put white piece
  614.                     tsReversi.PutTile(lpddsBack,TileX,TileY,10);
  615.                 }break;
  616.             case PIECEBLACK:
  617.                 {
  618.                     //put white piece
  619.                     tsReversi.PutTile(lpddsBack,TileX,TileY,24);
  620.                 }break;
  621.             case PIECETRANSIT:
  622.                 {
  623.                     //put transition piece
  624.                     tsReversi.PutTile(lpddsBack,TileX,TileY,iAnimation+10);
  625.                 }break;
  626.             }
  627.             //hilite last move
  628.             if(Board[x][y].bLastMove)
  629.             {
  630.                 tsReversi.PutTile(lpddsBack,TileX,TileY,25);
  631.             }
  632.         }
  633.     }
  634. }
  635.  
  636.  
  637. void ScanForMoves(int plyr)
  638. {
  639.     //loop through board
  640.     for(int x=0;x<8;x++)
  641.     {
  642.         for(int y=0;y<8;y++)
  643.         {
  644.             //check for a valid move
  645.             Board[x][y].bHilite=ValidMove(plyr,x,y);
  646.         }
  647.     }
  648. }
  649.  
  650. bool AnyValidMoves(int plyr)
  651. {
  652.     //scan the board
  653.     for(int x=0;x<8;x++)
  654.     {
  655.         for(int y=0;y<8;y++)
  656.         {
  657.             //a single valid move will return true
  658.             if(ValidMove(plyr,x,y))
  659.             {
  660.                 return(true);
  661.             }
  662.         }
  663.     }
  664.     return(false);//didnt find a move, return false
  665. }
  666.  
  667. bool ValidMove(int plyr,int x,int y)
  668. {
  669.     //loop through directions
  670.     for(int dir=DIR_NORTH;dir<DIR_COUNT;dir++)
  671.     {
  672.         //check for a valid run
  673.         if(ValidRun(plyr,x,y,dir))
  674.         {
  675.             //at least one valid run means the move is valid
  676.             return(true);
  677.         }
  678.     }
  679.  
  680.     //default to false
  681.     return(false);
  682. }
  683.  
  684. bool ValidRun(int plyr,int x,int y,int dir)
  685. {
  686.     //set distance to zero
  687.     int dist=0;
  688.     int piece=0;
  689.     for(;;)
  690.     {
  691.         //retrieve the piece
  692.         piece=Board[x][y].iPiece;
  693.  
  694.         switch(dist)
  695.         {
  696.         case 0:
  697.             {
  698.                 //if square is not empty, it is not a valid run
  699.                 if(piece!=PIECEEMPTY)
  700.                 {
  701.                     return(false);
  702.                 }
  703.             }break;
  704.         case 1:
  705.             {
  706.                 //check for bounds
  707.                 if(x<0) return(false);
  708.                 if(y<0) return(false);
  709.                 if(x>7) return(false);
  710.                 if(y>7) return(false);
  711.  
  712.                 //must have a piece of the opposing side
  713.                 if(piece!=(1-plyr))
  714.                 {
  715.                     return(false);
  716.                 }
  717.             }break;
  718.         default:
  719.             {
  720.                 //check for bounds
  721.                 if(x<0) return(false);
  722.                 if(y<0) return(false);
  723.                 if(x>7) return(false);
  724.                 if(y>7) return(false);
  725.  
  726.                 //piece cannot be empty
  727.                 if(piece==PIECEEMPTY)
  728.                 {
  729.                     return(false);
  730.                 }
  731.  
  732.                 //if piece is of the players color, it is a valid run
  733.                 if(piece==plyr)
  734.                 {
  735.                     return(true);
  736.                 }
  737.  
  738.             }break;
  739.         }
  740.         //move the x,y
  741.         x+=DeltaX(dir);
  742.         y+=DeltaY(dir);
  743.         dist++;
  744.     }
  745. }
  746.  
  747. int DeltaX(int dir)
  748. {
  749.     //switch on direction
  750.     switch(dir)
  751.     {
  752.         //directions that require leftward movememnt
  753.     case DIR_NORTHWEST:
  754.     case DIR_WEST:
  755.     case DIR_SOUTHWEST:
  756.         {
  757.             return(-1);
  758.         }break;
  759.         //directions that require rightward movement
  760.     case DIR_NORTHEAST:
  761.     case DIR_EAST:
  762.     case DIR_SOUTHEAST:
  763.         {
  764.             return(1);
  765.         }break;
  766.     }
  767.     return(0);//default to no movement
  768. }
  769.  
  770. int DeltaY(int dir)
  771. {
  772.     //switch on direction
  773.     switch(dir)
  774.     {
  775.     case DIR_NORTHWEST:
  776.     case DIR_NORTH:
  777.     case DIR_NORTHEAST:
  778.         {
  779.             //upward
  780.             return(-1);
  781.         }break;
  782.     case DIR_SOUTHWEST:
  783.     case DIR_SOUTH:
  784.     case DIR_SOUTHEAST:
  785.         {
  786.             //downward
  787.             return(1);
  788.         }break;
  789.     }
  790.     return(0);//default to no movement
  791. }
  792.  
  793. void MakeMove(int plyr,int x,int y)
  794. {
  795.  
  796.     //store valid runs
  797.     bool Run[DIR_COUNT];
  798.     int dir=0;
  799.     for(dir=DIR_NORTH;dir<DIR_COUNT;dir++)
  800.     {
  801.         Run[dir]=ValidRun(plyr,x,y,dir);
  802.     }
  803.  
  804.     //set pieces to transitory state
  805.     int tx;//tx is a temporary x coordinate
  806.     int ty;
  807.     for(dir=DIR_NORTH;dir<DIR_COUNT;dir++)
  808.     {
  809.         //must be a valid run
  810.         if(Run[dir])
  811.         {
  812.             //set first position
  813.             tx=x+DeltaX(dir);
  814.             ty=y+DeltaY(dir);
  815.  
  816.             //while still on an opposing piece
  817.             while(Board[tx][ty].iPiece==(1-plyr))
  818.             {
  819.                 //set piece to transit
  820.                 Board[tx][ty].iPiece=PIECETRANSIT;
  821.                 //update x,y position
  822.                 tx+=DeltaX(dir);
  823.                 ty+=DeltaY(dir);
  824.             }
  825.         }
  826.     }
  827.  
  828.     //set the appropriate animation value
  829.     switch(plyr)
  830.     {
  831.     case PLAYERTWO:
  832.         {
  833.             //animation value of 14
  834.             iAnimation=14;
  835.         }break;
  836.     case PLAYERONE:
  837.         {
  838.             //animation value of 0
  839.             iAnimation=0;
  840.         }break;
  841.     }
  842.  
  843.     //set initial piece
  844.     Board[x][y].iPiece=plyr;
  845.  
  846. }
  847.  
  848. void FinishMove(int plyr)
  849. {
  850.     //scan board
  851.     for(int x=0;x<8;x++)
  852.     {
  853.         for(int y=0;y<8;y++)
  854.         {
  855.             //if a transit piece
  856.             if(Board[x][y].iPiece==PIECETRANSIT)
  857.             {
  858.                 //set to player's piece
  859.                 Board[x][y].iPiece=plyr;
  860.             }
  861.         }
  862.     }
  863. }
  864.  
  865. void MakeRandomMove(int plyr)
  866. {
  867.     int x;
  868.     int y;
  869.     //pick a valid, random move
  870.     for(;;)
  871.     {
  872.         //pick random square
  873.         x=rand()%8;
  874.         y=rand()%8;
  875.         //if a valid move, break out of the loop
  876.         if(ValidMove(plyr,x,y)) break;
  877.     }
  878.     //make the move
  879.     MakeMove(plyr,x,y);
  880.     iGameState=GS_FLIP;
  881.     SetLastMove(x,y);
  882. }
  883.  
  884. void MakeGreedyMove(int plyr)
  885. {
  886.     //loop vars
  887.     int x;
  888.     int y;
  889.     //backup the board
  890.     SaveBoard();
  891.     //make an ai array for judging moves
  892.     int AI[8][8];
  893.     int hival=0;
  894.     //loop through board squares
  895.     for(x=0;x<8;x++)
  896.     {
  897.         for(y=0;y<8;y++)
  898.         {
  899.             //restore the board
  900.             RestoreBoard();
  901.             //check for valid move
  902.             if(ValidMove(plyr,x,y))
  903.             {
  904.                 //valid move
  905.                 MakeMove(plyr,x,y);
  906.                 FinishMove(plyr);
  907.                 AI[x][y]=GetScore(plyr);
  908.             }
  909.             else
  910.             {
  911.                 //non-valid move
  912.                 AI[x][y]=0;
  913.             }
  914.             //new high value
  915.             if(AI[x][y]>hival)
  916.             {
  917.                 hival=AI[x][y];
  918.             }
  919.         }
  920.     }
  921.     //restore the board
  922.     RestoreBoard();
  923.     //find a square
  924.     for(;;)
  925.     {
  926.         //pick random square
  927.         x=rand()%8;
  928.         y=rand()%8;
  929.         //check against hival
  930.         if(AI[x][y]==hival) break;
  931.     }
  932.     MakeMove(plyr,x,y);
  933.     iGameState=GS_FLIP;
  934.     SetLastMove(x,y);
  935. }
  936.  
  937. void MakeMiserMove(int plyr)
  938. {
  939.     //loop vars
  940.     int x;
  941.     int y;
  942.     //temp x and y
  943.     int tx;
  944.     int ty;
  945.     //backup the board
  946.     SaveBoard();
  947.     //make an ai array for judging moves
  948.     int AI[8][8];
  949.     int loval=0x7FFFFFFF;
  950.     //loop through board squares
  951.     for(x=0;x<8;x++)
  952.     {
  953.         for(y=0;y<8;y++)
  954.         {
  955.             AI[x][y]=0;
  956.             //restore the board
  957.             RestoreBoard();
  958.             //check for valid move
  959.             if(ValidMove(plyr,x,y))
  960.             {
  961.                 //weight the moves
  962.                 //edges
  963.                 if(x==0) AI[x][y]-=2;
  964.                 if(x==7) AI[x][y]-=2;
  965.                 if(y==0) AI[x][y]-=2;
  966.                 if(y==7) AI[x][y]-=2;
  967.                 //corners
  968.                 if((x==0) && (y==0)) AI[x][y]-=6;
  969.                 if((x==7) && (y==0)) AI[x][y]-=6;
  970.                 if((x==0) && (y==7)) AI[x][y]-=6;
  971.                 if((x==7) && (y==7)) AI[x][y]-=6;
  972.  
  973.                 //valid move
  974.                 MakeMove(plyr,x,y);
  975.                 FinishMove(plyr);
  976.                 //loop to count valid moves for opposing player
  977.                 for(tx=0;tx<8;tx++)
  978.                 {
  979.                     for(ty=0;ty<8;ty++)
  980.                     {
  981.                         //count valid moves
  982.                         if(ValidMove(1-plyr,tx,ty))
  983.                         {
  984.                             AI[x][y]++;
  985.                             //edges
  986.                             if(tx==0) AI[x][y]+=1;
  987.                             if(tx==7) AI[x][y]+=1;
  988.                             if(ty==0) AI[x][y]+=1;
  989.                             if(ty==7) AI[x][y]+=1;
  990.                             //corners
  991.                             if((tx==0) && (ty==0)) AI[x][y]+=3;
  992.                             if((tx==7) && (ty==0)) AI[x][y]+=3;
  993.                             if((tx==0) && (ty==7)) AI[x][y]+=3;
  994.                             if((tx==7) && (ty==7)) AI[x][y]+=3;
  995.                         }
  996.                     }
  997.                 }
  998.             }
  999.             else
  1000.             {
  1001.                 //not a valid move
  1002.                 AI[x][y]=0x7FFFFFFF;
  1003.             }
  1004.             //new high value
  1005.             if(AI[x][y]<loval)
  1006.             {
  1007.                 loval=AI[x][y];
  1008.             }
  1009.         }
  1010.     }
  1011.     //restore the board
  1012.     RestoreBoard();
  1013.     //find a square
  1014.     for(;;)
  1015.     {
  1016.         //pick random square
  1017.         x=rand()%8;
  1018.         y=rand()%8;
  1019.         //check against hival
  1020.         if(AI[x][y]==loval) break;
  1021.     }
  1022.     MakeMove(plyr,x,y);
  1023.     iGameState=GS_FLIP;
  1024.     SetLastMove(x,y);
  1025. }
  1026.  
  1027. int GetScore(int plyr)
  1028. {
  1029.     int score=0;
  1030.     //loop through board
  1031.     for(int x=0;x<8;x++)
  1032.     {
  1033.         for(int y=0;y<8;y++)
  1034.         {
  1035.             //if piece belongs to plr, add to score
  1036.             if(Board[x][y].iPiece==plyr) score++;
  1037.         }
  1038.     }
  1039.     return(score);
  1040. }
  1041.  
  1042. void ShowScores()
  1043. {
  1044.     //score and counter
  1045.     int score;
  1046.     int counter;
  1047.     //player one score
  1048.     score=GetScore(PLAYERONE);
  1049.     //show a column of player one's pieces
  1050.     for(counter=0;counter<score;counter++)
  1051.     {
  1052.         tsReversi.PutTile(lpddsBack,0,4*counter,24);
  1053.     }
  1054.     //player two score
  1055.     score=GetScore(PLAYERTWO);
  1056.     //show columns of player two's pieces
  1057.     for(counter=0;counter<score;counter++)
  1058.     {
  1059.         tsReversi.PutTile(lpddsBack,(tsReversi.GetTileList()[0].rcSrc.right-tsReversi.GetTileList()[0].rcSrc.left),4*counter,10);
  1060.     }
  1061. }
  1062.  
  1063. void SetLastMove(int x, int y)
  1064. {
  1065.     //temp x and y for loops
  1066.     for(int tx=0;tx<8;tx++)
  1067.     {
  1068.         for(int ty=0;ty<8;ty++)
  1069.         {
  1070.             //clear the lastmove
  1071.             Board[tx][ty].bLastMove=false;
  1072.         }
  1073.     }
  1074.     //set new last move
  1075.     Board[x][y].bLastMove=true;
  1076. }
  1077.  
  1078. void ShowPlayers()
  1079. {
  1080.     //grab tile width
  1081.     int iTileWidth=tsReversi.GetTileList()[0].rcSrc.right-tsReversi.GetTileList()[0].rcSrc.left;
  1082.     //grab tile height
  1083.     int iTileHeight=tsReversi.GetTileList()[0].rcSrc.bottom-tsReversi.GetTileList()[0].rcSrc.top;
  1084.  
  1085.     //show player 1
  1086.     tsReversi.PutTile(lpddsBack,0,600-iTileHeight,24);
  1087.     //show AI level
  1088.     tsReversi.PutTile(lpddsBack,0,600-iTileHeight,26+iAILevel[PLAYERONE]);
  1089.     //show player 2
  1090.     tsReversi.PutTile(lpddsBack,iTileWidth,600-iTileHeight,10);
  1091.     //show AI level
  1092.     tsReversi.PutTile(lpddsBack,iTileWidth,600-iTileHeight,26+iAILevel[PLAYERTWO]);
  1093.     //show current player
  1094.     tsReversi.PutTile(lpddsBack,iTileWidth*iPlayer,600-iTileHeight,25);
  1095. }
  1096.